enum Color {
    bg = 0xAAAAAA,// 棋盘背景 
    grey = 0x808080,
    dark = 0x111111,
    orange = 0xF08080,
    red = 0xff0000,
    green = 0xff00,
    blue = 0xff,
    yellow = 0xffff00,
    pink = 0xff00ff,
    cyan = 0xffff,
    purple = 0x800080,
    olive = 0x8080000,
    teal = 0x008080,
}

function randomColor() {
    let cs = [Color.red, Color.green, Color.blue,
    Color.yellow, Color.pink, Color.cyan,
    Color.purple, Color.olive, Color.teal]

    return cs[Math.floor(Math.random() * cs.length)];
}

function randomShape() {
    let values = Object.values(BrickShape);
    return values[Math.floor(Math.random() * values.length)];
}

/**
 * @summary 基本方块类
 */
class Squar extends egret.Shape {

    lineColor: Color;
    fillColor: Color;
    lineWidth: number;

    static len: number = 60;
    /**
     * @summary 基本方块构造函数(默认是棋盘背景)
     * @param fillColor 填充颜色
     * @param lineColor 边框颜色
     * @param lineWidth 边框宽度
     */
    constructor(fillColor: Color = Color.bg, lineColor: Color = Color.grey, lineWidth: number = 1) {
        super();
        this.fillColor = fillColor;
        this.lineColor = lineColor;
        this.lineWidth = lineWidth;

        this.addEventListener(egret.Event.ADDED_TO_STAGE, this.onAddToStage, this);
    }
    private onAddToStage(evt: egret.Event) {
        this.draw();
    }
    draw() {
        this.graphics.clear();
        this.graphics.lineStyle(this.lineWidth, this.lineColor);
        this.graphics.beginFill(Color.bg, 0.9);
        this.graphics.drawRect(0, 0, Squar.len, Squar.len);
        if(this.fillColor != Color.bg) {
            this.graphics.beginFill(this.fillColor, 0.9);
            this.graphics.drawRect(1, 1, Squar.len-2, Squar.len-2);
        }
        this.graphics.endFill();
    }
}

/**
 * @summary 棋盘类
 */
class Board extends eui.Component {
    squars: Squar[][];
    constructor() {
        super();
        this.addEventListener(egret.Event.ADDED_TO_STAGE, this.onAddToStage, this);

        this.squars = new Array(10);
        for (let i = 0; i < 10; i++) {
            this.squars[i] = new Array(10);
            for (let j = 0; j < 10; j++) {
                this.squars[i][j] = new Squar();
                this.squars[i][j].x = j * Squar.len;
                this.squars[i][j].y = i * Squar.len;
                this.addChild(this.squars[i][j]);
            }
        }
    }
    private onAddToStage(evt: egret.Event) {
        this.draw();
    }
    reset() {
        for (let i = 0; i < 10; i++) {
            for (let j = 0; j < 10; j++) {
                this.squars[i][j].fillColor = Color.bg;
            }
        }
        this.draw();
    }
    draw() {
        for (let i = 0; i < 10; i++) {
            for (let j = 0; j < 10; j++) {
                this.squars[i][j].draw();
            }
        }
    }

    private rowCheck(row: number) {
        for (let i = 0; i < 10; i++) {
            if (this.squars[row][i].fillColor == Color.bg)
                return false;
        }
        return true;
    }
    private colCheck(col: number) {
        for (let i = 0; i < 10; i++) {
            if (this.squars[i][col].fillColor == Color.bg)
                return false;
        }

        return true;
    }

    /**
     * @summary 在索引(row,col)处放置砖块
     * @param row 行(0-based)
     * @param col 列(0-based)
     * @param brick 砖块
     * 
     * @returns 消除的行数
     */
    place(row: number, col: number, brick: Brick) {
        let brickWidth = 0;
        for (let i = 0; i < brick.Shape.length; i++) {
            if (brick.Shape[i].length > brickWidth)
                brickWidth = brick.Shape[i].length;
            for (let j = 0; j < brick.Shape[i].length; j++) {
                if (brick.Shape[i][j] != 0) {
                    this.squars[row + i][col + j].fillColor = brick.color;
                    this.squars[row + i][col + j].draw();
                }
            }

        }
        //检查是否可以消除 
        let eraseLine = 0;
        let rowErase = [], colErase = [];
        for (let i = row; i < row + brick.Shape.length; i++) {
            if (this.rowCheck(i)) {
                eraseLine++;
                rowErase.push(i);
            }
        }
        for (let i = col; i < col + brickWidth; i++) {
            if (this.colCheck(i)) {
                eraseLine++;
                colErase.push(i);
            }
        }
        rowErase.forEach((row) => {
            for (let i = 0; i < 10; i++) {
                this.squars[row][i].fillColor = Color.bg;
                this.squars[row][i].draw();
            }
        });
        colErase.forEach((col) => {
            for (let i = 0; i < 10; i++) {
                this.squars[i][col].fillColor = Color.bg;
                this.squars[i][col].draw();
            }
        });

        return eraseLine;
    }
    /**
     * @summary 尝试在索引(row, col)处放置砖块，可放置返回true，否则返回false
     * @param row 行(0-based)
     * @param col 列(0-based)
     * @param brick 砖块
     */
    tryPlace(row: number, col: number, brick: Brick): boolean {
        for (let i = 0; i < brick.Shape.length; i++) {
            for (let j = 0; j < brick.Shape[i].length; j++) {
                if (col + j > 9 || row + i > 9)
                    return false;
                if (this.squars[row + i][col + j].fillColor != Color.bg && brick.Shape[i][j] != 0) {
                    return false;
                }

            }
        }

        return true;
    }

    /**
     * @summary 当前棋盘是否可放置砖块，可放置返回true，否则返回false 
     * @param brick 砖块
     */
    isPlacable(brick: Brick): boolean {
        for (let i = 0; i < 10; i++) {
            for (let j = 0; j < 10; j++) { 
                if (this.tryPlace(i, j, brick))
                    return true;
            }
        }
        return false;
    }
}

 
class MarkShape extends egret.Shape {
    constructor() {
        super(); 
        this.draw();
    }
    draw() { 
        this.graphics.clear();
    }
    drawTick() {
        this.graphics.clear();
        this.graphics.beginFill(0x333333, 0.7);
        this.graphics.lineStyle(2, 0x252525);
        this.graphics.drawCircle(0, 0, 20);
        this.graphics.endFill();
        this.graphics.lineStyle(4, 0xFF00);
        this.graphics.moveTo(-10, -3);
        this.graphics.lineTo(-2, 8);
        this.graphics.lineTo(10, -8);
    }

    drawError() {
        this.graphics.clear();
        this.graphics.beginFill(0x333333, 0.7);
        this.graphics.lineStyle(2, 0x252525);
        this.graphics.drawCircle(0, 0, 20);
        this.graphics.endFill();
        this.graphics.lineStyle(4, 0xFF0000);
        this.graphics.moveTo(-8, -8);
        this.graphics.lineTo(8,8);
        this.graphics.moveTo(-8, 8);
        this.graphics.lineTo(8, -8);
    }
}

/**
 * @summary 砖块类
 */
class Brick extends egret.Shape {
    color: number;
    private _shape: number[][];
    isShadow: Boolean;

    constructor(color: number = Color.red, shape: number[][] = [], isShadow: Boolean = false) {
        super();

        this.color = color;
        this._shape = shape;
        this.isShadow = isShadow;


        this.addEventListener(egret.Event.ADDED_TO_STAGE, this.onAddToStage, this);
    }

    private onAddToStage(evt: egret.Event) {
        this.draw();
    }

    draw() {
        let fillColor = this.isShadow ? Color.grey : this.color;
        let lineColor = this.isShadow ? Color.yellow : Color.dark;
        let lineWidth = this.isShadow ? 2 : 1;

        this.graphics.clear();
        this.graphics.beginFill(fillColor, 0.8);
        this.graphics.lineStyle(lineWidth, lineColor);
        for (let i = 0; i < this.Shape.length; i++) {
            for (let j = 0; j < (this.Shape[i]).length; j++) {
                if (this.Shape[i][j] != 0)
                    this.graphics.drawRect(j * Squar.len +1, i * Squar.len+1, Squar.len-2, Squar.len-2);
            }
        }
        this.graphics.endFill();
    }

    get Shape(): number[][] {
        return this._shape;
    }
    set Shape(shape: number[][]) {
        this._shape = shape;
        this.graphics.clear();
        for (let i = 0; i < this.Shape.length; i++) {
            for (let j = 0; j < (this.Shape[i]).length; j++) {
                if (this.Shape[i][j] != 0)
                    this.graphics.drawRect(j * Squar.len, i * Squar.len, Squar.len, Squar.len);
            }
        }
    }
}

enum BrickStatus{
    Placed,
    Placeable,
    Forbidden
}
class StageBrick {
    brick:Brick = new Brick();
    mark:MarkShape = new MarkShape();
    status:BrickStatus = BrickStatus.Placeable;
}
/**
 * 
 */
const BrickShape = {
    L: [[1], [1], [1, 1, 1]],
    L_Mirror: [[0, 0, 1], [0, 0, 1], [1, 1, 1]],
    L_UPDOWN: [[1, 1, 1], [1], [1]],
    L_UPDOWN_Mirror: [[1, 1, 1], [0, 0, 1], [0, 0, 1]],

    T: [[1, 1, 1], [0, 1], [0, 1]],
    T_LRotate: [[1], [1, 1, 1], [1]],
    T_UPDOWN: [[1], [1], [1, 1, 1]],
    T_RRotate: [[0, 0, 1], [1, 1, 1], [0, 0, 1]],

    N: [[0, 0, 1], [1, 1, 1], [1]],
    N_LRotate: [[1, 1], [0, 1], [0, 1, 1]],
    N_UPDOWN: [[1], [1, 1, 1], [0, 0, 1]],
    N_UPDOWN_Mirror: [[0, 0, 1], [1, 1, 1], [1]],

    C: [[1, 1], [1], [1, 1]],
    C_LRotate: [[1, 0, 1], [1, 1, 1]],
    C_RRotate: [[1, 1, 1], [1, 0, 1]],
    C_Mirror: [[1, 1], [0, 1], [1, 1]],

    Rec_2: [[1, 1], [1, 1]],
    Rec_3: [[1, 1, 1], [1, 1, 1], [1, 1, 1]],
    Dot: [[1]],
    Wide: [[1, 1, 1, 1]],
    Tall: [[1], [1], [1], [1]],

    1: [[1], [1, 1]],
    2: [[0, 1], [1, 1]],
    3: [[1, 1], [1]],
    4: [[1, 1], [0, 1]],

    5: [[1, 1, 1], [0, 1]],
    6: [[1], [1, 1], [1]],
    7: [[0, 1], [1, 1], [0, 1]],
    8: [[0, 1], [1, 1, 1]],
    9: [[1, 1]],
    10: [[1], [1]],
    11: [[1, 1, 1]],
    12: [[1], [1], [1]],
    21: [[1,1],[0,1,1]],
    22: [[0,1,1],[1,1]],
    23: [[1,0],[1,1],[0,1]],
    24: [[0,1],[1,1],[1]],

    551: [[1], [1, 1]],
    552: [[0, 1], [1, 1]],
    553: [[1, 1], [1]],
    554: [[1, 1], [0, 1]],

    555: [[1, 1, 1], [0, 1]],
    556: [[1], [1, 1], [1]],
    557: [[0, 1], [1, 1], [0, 1]],
    558: [[0, 1], [1, 1, 1]],
    559: [[1, 1]],
    510: [[1], [1]],
    511: [[1, 1, 1]],
    512: [[1], [1], [1]],

}

class InfoPanel extends eui.Component{
    constructor() {
        super();  
    }
    clear() { 
        this.removeChildren(); 
    }
    draw(text:string) {
        this.width = 500;
        this.height = 500;

        let bg = new egret.Shape();
        bg.graphics.beginFill(0x151515,0.7);
        bg.graphics.drawRoundRect(0,0,500,500,50,50);
        bg.graphics.endFill();
        this.addChild(bg);
        
        let info = new egret.TextField()
        info.text = text;
        info.textColor = 0xff0000;
        info.multiline = true;
        info.textAlign = "center";
        info.verticalAlign = "center";
        info.width = 500;
        info.height = 500;
        info.size = 52;
        this.addChild(info); 
        info.y = 200;
    }
}
